/**
 * @fileOverview Webkit Notification API jQuery Wrapper
 *
 * @see http://www.chromium.org/developers/design-documents/desktop-notifications/api-specification
 * @see http://www.html5rocks.com/en/tutorials/notifications/quick/
 *
 * @author azproduction
 * @licence MIT (c) azproduction 2011
 */
jQuery.notification = (function ($, window) {

/**
 * @see http://www.w3.org/TR/notifications/
 *
 * @type {Function}
 */
var W3CNotification = (function () {
    // Safari 6+ Firefox 22+
    if (window.Notification && (window.Notification.permissionLevel || window.Notification.permission)) return window.Notification;

    var webkitNotifications = window.webkitNotifications;

    // Non Webkit browsers
    if (!webkitNotifications) return (function () {
        var mockWebkitNotifications = {};
        mockWebkitNotifications.permission = "unsupported";
        mockWebkitNotifications.permissionLevel = function () {
            return "unsupported";
        };
        mockWebkitNotifications.requestPermission = $.noop;

        return mockWebkitNotifications;
    }());

    // 1 undefined
    // 2 forbidden
    // 0 allowed
    var notificationPermission = ["granted", "default", "denied"];

    // Older WebKit browsers
    var Notification = function (title, options) {
        options = options || {};
        if (!title) {
            return;
        }
        var instance = webkitNotifications.createNotification(options.iconUrl || "", title, options.body || "");

        instance.titleDir = options.titleDir || "auto";
        instance.body = options.body || "";
        instance.bodyDir = options.bodyDir || "auto";
        instance.tag = options.tag || "";
        instance.replaceId = options.tag || "";
        instance.iconUrl = options.iconUrl || "";

        instance.onclick = options.onclick || $.noop;
        instance.onshow = options.onshow || $.noop;
        instance.onerror = options.onerror || $.noop;
        instance.onclose = options.onclose || $.noop;
        instance.close = function () {
            instance.cancel();
        };

        if (Notification.permissionLevel() === "granted") {
            instance.show();
        }

        return instance;
    };

    Notification.permissionLevel = function () {
        return Notification.permission = notificationPermission[webkitNotifications.checkPermission()];
    };

    Notification.permissionLevel();

    Notification.requestPermission = function (callback) {

        if (Notification.permissionLevel() !== "default") {
            callback();
            return;
        }

        if (webkitNotifications.requestPermission.length) {
            webkitNotifications.requestPermission(function () {
                Notification.permissionLevel();
                callback();
            });
            return;
        }

        // In old chrome webkitNotifications.requestPermission is without callback LOL
        webkitNotifications.requestPermission();
        var checkPermissionInterval = window.setInterval(function () {
            var permissionLevel = Notification.permissionLevel();

            if (permissionLevel !== "default") {
                window.clearInterval(checkPermissionInterval);
                callback();
            }
        }, 200);
    };

    return Notification;
}());

var requestPermission = function (callback) {
    if ((W3CNotification.permission || W3CNotification.permissionLevel()) !== "default") {
        callback();
        return;
    }

    $(document).one('click', function () {
        W3CNotification.requestPermission(callback);
    });
};

/**
 * Notification
 *
 * @constructor
 *
 * @param {Object}   options                  if url passed -> HTML page mode else icon & title & content mode
 * @param {String}   [options.iconUrl]
 * @param {String}   [options.title]
 * @param {String}   [options.body]
 * @param {String}   [options.tag]            acts as window.name in window.open
 * @param {Function} [options.onclick]
 * @param {Function} [options.onclose]
 * @param {Function} [options.onshow]
 * @param {Function} [options.onerror]
 * @param {Boolean}  [options.autoclose=true] close block on click? close button is to small so its enable by default
 * @param {Number}   [options.timeout=Infinity] notification auto-close timeout
 *
 * @example
 *
 *      var message = $.notification(options);
 *      // messge will displayed as soon as user permit notifications
 *
 * @return {Deferred}
 */
var exports = function (options) {
    var dfd = $.Deferred();

    // Wired Safari 6 hack...
    if (!W3CNotification.prototype) {
        dfd.reject('unsupported');
        return dfd.promise();
    }

    if (typeof options === "string") {
        options = {
            title: options
        };
    }
    options = options || {};
    options.autoclose = typeof options.autoclose === "undefined" ? true : options.autoclose;
    options.timeout = options.timeout || Infinity;

    // fix older iconUrl
    var icon = options.iconUrl || options.icon;
    if (icon) {
        options.icon = icon;
    }

    requestPermission(function () {
        var level = W3CNotification.permission || W3CNotification.permissionLevel();
        if (level !== "granted") {
            dfd.reject(level);
            return;
        }

        var instance = new W3CNotification(options.title, options);

        if (isFinite(options.timeout)) {
            instance.addEventListener('show', function () {
                setTimeout(function () {
                    instance.close();
                }, options.timeout);
            }, false);
        }

        if (options.autoclose) {
            instance.addEventListener('click', function () {
                instance.close();
            }, false)
        }

        dfd.resolve(instance);
    });

    return dfd.promise();
};

exports.permission = W3CNotification.permission;
exports.permissionLevel = W3CNotification.permissionLevel || function () {
    return W3CNotification.permission;
};
exports.requestPermission = requestPermission;

return exports;

}(jQuery, window));
